﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Disposables;
using System.Linq;
using System.Linq.Expressions;
using System.Windows;
using System.Windows.Data;
using SoftSource.Common;
using SoftSource.Timecard.ViewModelInterfaces;
using SoftSource.Timecard.Web.Data;
using SoftSource.Reactive;

namespace SoftSource.Timecard.ViewModels
{
    public sealed class EntryManagementViewModel : IEntryManagementViewModel
    {
        #region Fields
        private CompositeDisposable compositeDisposable;
        private PagedCollectionView projects;
        private PagedCollectionView users;
        private IEnumerable<EntryLog> entrySource;
        private IEnumerable<ProjectSummary> projectSource;
        private IEnumerable<UserSummary> userSource;
        #endregion Fields

        public EntryManagementViewModel()
        {
            this.compositeDisposable = new CompositeDisposable();
            this.Entries = new ObservableProperty<PagedCollectionView>();
            var disposable = this.Entries.Subscribe(value =>
                {
                    if (value != null)
                    {
                        value.SortDescriptions.Add(new SortDescription(
                            ObjectReflection.GetPropertyName<EntryLog>(e => e.EntryDate),
                            ListSortDirection.Descending));
                        this.PropertyChanged.Notify(() => this.Entries);
                    }
                });

            this.compositeDisposable.Add(disposable);
        }

        #region IEntryManagementViewModelConsume Members

        public IObservableProperty<PagedCollectionView> Entries { get; private set; }

        public PagedCollectionView Projects
        {
            get { return this.projects; }
            private set
            {
                this.projects = value;
                this.Projects.SortDescriptions.Add(new SortDescription(
                    ObjectReflection.GetPropertyName<ProjectSummary>(p => p.Name),
                    ListSortDirection.Ascending));
                this.projects.MoveCurrentToFirst();
                this.PropertyChanged.Notify(() => this.Projects);
            }
        }

        public PagedCollectionView Users
        {
            get { return this.users; }
            private set
            {
                this.users = value;
                this.Users.SortDescriptions.Add(new SortDescription(
                    ObjectReflection.GetPropertyName<UserSummary>(u => u.FullName),
                    ListSortDirection.Ascending));
                this.users.MoveCurrentToFirst();
                this.PropertyChanged.Notify(() => this.Users);
            }
        }

        public IObservable<Unit> Load { get; set; }

        public Func<int?, int?, DateTime?, DateTime?, IObservable<Unit>> Refresh { get; set; }
        public IObservable<Unit> SaveApprovals { get; set; }
        public Func<EntryLog, Action, UIElement> EditEntryAssociations { get; set; }

        #endregion

        #region IEntryManagementViewModelService Members

        public IEnumerable<EntryLog> EntrySource
        {
            get { return this.entrySource; }
            set
            {
                this.entrySource = value;
                this.Entries.Value = new PagedCollectionView(this.entrySource);
            }
        }

        public IEnumerable<ProjectSummary> ProjectSource
        {
            get { return this.projectSource; }
            set
            {
                this.projectSource = value;
                this.Projects = new PagedCollectionView(this.projectSource);
            }
        }

        public IEnumerable<UserSummary> UserSource
        {
            get { return this.userSource; }
            set
            {
                this.userSource = value;
                this.Users = new PagedCollectionView(this.userSource);
            }
        }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            this.compositeDisposable.Dispose();
            GC.SuppressFinalize(this);
        }

        #endregion

        ~EntryManagementViewModel()
        {
            this.Dispose();
        }
    }
}
